package ControllerLayer;
import ModelLayer.*;

import java.util.*;
/**
 * OrderCtr functions as a controller for the OrderCon and Order classes in the ModelLayer.
 * Any changes to instances of those classes will go through this controller.
 * 
 * @author  Anders A.P., Mie P., Danny M.P., Jakob K., Anna K.  
 * @version 1.0
 */
public class OrderCtr {

    private OrderCon    orderCon;    
    private EmployeeCtr employeeCtr;
    private CustomerCtr customerCtr;
    private ItemCtr     itemCtr;
    private Order       o;

    /**
     * Constructor for objects of class OrderCtr
     */
    public OrderCtr() {

        orderCon = OrderCon.getInstance();
        employeeCtr = new EmployeeCtr();
        customerCtr = new CustomerCtr();
        itemCtr = new ItemCtr();

    }

    /** 
     * Method for creating a new order, adding the current employee to it,
     * and adding it to the container.
     */
    public void startOrder() {
        o = new Order();
        Employee e = employeeCtr.getCurrentEmployee();
        o.addEmployee(e);
        o.setIsOffer(false);
    }

    /**
     * Method for setting the variable o to a given order.
     * 
     * @param   o   the given orderobject which is to be manipulated.
     */
    public void setOrder(Order o) {

        this.o = o;

    }
    
    /**
     * Method for setting the boolean isOffer false
     */
    public void offerToOrder()
    {
        o.setIsOffer(false);
    }

    /**
     * Method for adding a customer to an order or an offer, verifying whether packing and delivery
     * is wanted.
     *
     * @param customerNo  the unique customernumber used to retrieve a customerobject.
     * @param packing     a boolean for whether packing is wanted or not.
     * @param delivery    a boolean for whether delivery is wanted or not.
     */
    public void addCustomer(int customerNo, boolean packing, boolean delivery) {

        Customer c = customerCtr.getCustomer(customerNo);
        if(c == null) {
            throw new IllegalArgumentException("Kunden ikke fundet");
        }
        o.updateOrder(c, packing, delivery);
        if(o.getIsOffer()) {
            o.getCustomer().addOffer(o);
        }
        else {
            o.getCustomer().addOrder(o);
        }

    }

    /**
     * Method to return the current employee.
     *
     * @return  currentEmployee     the employee currently logged into the system.
     */
    public Employee getCurrentEmployee() {

        return employeeCtr.getCurrentEmployee();

    }
    
    /**
     * Method for adding an item with a given quantity to an order.
     * Creates an OrderLine object, and adds it to the Order object.
     * 
     * @param itemID    the ID used to find the item.
     * @param quantity  the quantity of the item.
     * 
     * @throws Exception if item is not found.
     * @throws Exception if quantity is zero.
     */
    public void addItem(int itemID, int quantity) throws Exception {

        Item i = itemCtr.retrieveItem(itemID);
        OrderLine ol = new OrderLine(i, quantity);
        o.addOrderLine(ol);

    }

    /**
     * Method for ending a offer. Will return the total price to the UI layer.
     *
     * @return  totalPrice  the total price of the order as a double.
     */
    public double endOrder() {

        if(o.getCustomer() != null) {
            o.getCustomer().removeOffer(o);
            o.getCustomer().addOrder(o);
        }
        orderCon.addOrder(o);
        return o.endOrder();

    }

    /**
     * Method for returning a given customer's offers to the UI, 
     * from which a single can be chosen.
     *
     * @param   customerNo                  customer ID.
     * @return  ArrayList<Order>(offers)    an arraylist containing offers.
     */
    public ArrayList<Order> findOffer(int customerNo) {

        return customerCtr.getCustomerOffers(customerNo);

    }                

    /**
     * Method for returning the change, given a set amount.
     *
     * @param   amount      amount payed by the customer.
     * @return  cashBack    the deficit between the order total price, and the inserted 
     *                      value as a double.
     */
    public double makePayment(double amount) {

        return o.registerPayment(amount);

    }

    /**
     * Method for returning the order.
     *
     * @return  o   the given Order object being manipulated.
     */
    public Order getOrder() {

        return o;

    }

}